package share.servlet;

import java.io.IOException;
import java.net.URLDecoder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eu.base.buffer.BufferFactory;
import org.eu.base.buffer.BufferPool;
import org.eu.base.security.AuthFilter;

import share.download.utils.DownloadThreadLimiter;
import share.download.utils.SingleThreadSpeedLimiter;
import share.storage.DirectoryTree;
import share.storage.io.DownloadType;
import share.storage.io.File;
import share.storage.io.FileReader;

public class DownloadServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	//BufferPool<File> bp = null;

	public DownloadServlet() {
//		bp = new BufferFactory<File>().newBufferPool(
//				"sharer", 2, true);
	}

	public void destroy() {
		super.destroy();
	}

	@Override
	protected void service(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		// 获取文件URI
		DownloadThreadLimiter dtl=new DownloadThreadLimiter(request);
		if(!dtl.registerNewThread()){
			response.sendError(503);
			return;
		}
		String path = URLDecoder
				.decode(request.getRequestURI().replace(
						getServletContext().getContextPath() + "/download", ""),
						"UTF-8");
		// 获取文件
//		File file = bp.get(path);
//		if (file == null) {
		DirectoryTree dt = DirectoryTree.getInstance();
		File file = dt.findByPath(path);
//			if (file == null) {
//				response.sendError(404);
//				return;
//			}
//			bp.put(path, file);
//		}
		// 获取文件读取对象
		FileReader fr = file.getReader();
		if(fr.getDownloadType()==DownloadType.JUMP){
			response.sendRedirect(fr.getLocation());
			return;
		}
		// 文件名
		String filename = file.getFilename();
		response.reset();
		// 响应头
		response.setContentType("application/octet-stream;charset=UTF-8");
		// 下载起始位置
		long since = 0;
		// 下载结束位置
		long until = file.getSize() - 1;
		// 获取Range，下载范围
		String range = request.getHeader("range");
		if (range != null) {
			response.setStatus(206);
			// 剖解range
			range = range.split("=")[1];
			String[] rs = range.split("-");
			if (AuthFilter.isDigit(rs[0])) {
				since = Long.parseLong(rs[0]);
			}
			if (rs.length > 1 && AuthFilter.isDigit(rs[1])) {
				until = Long.parseLong(rs[1]);
			}
		}else
			response.setStatus(200);
		// 设置响应头
		response.setHeader("Accept-Ranges", "bytes");
		response.setHeader("Content-Range", "bytes " + since + "-" + until
				+ "/" + file.getSize());
		// 文件名用ISO08859_1编码
		response.setHeader("Content-Disposition", "attachment; filename=\""
				+ new String(filename.getBytes(), "ISO8859_1") + "\"");
		response.setHeader("Content-Length", "" + (until - since + 1));
		// 定位到请求位置
		fr.seek(since);
		// 单次输出字节数
		final int PerSize = 1024;
		// 缓冲
		byte[] buffer = new byte[PerSize];
		// 读取长度
		int len;
		// 读满标志位
		boolean full = false;
		// 下载限速器
		SingleThreadSpeedLimiter stsl = new SingleThreadSpeedLimiter();
		// 读取，输出流
		try{
		while ((len = fr.read(buffer)) > 0) {
			if (fr.tell() - 1 > until) {
				len = (int) (len - (fr.tell() - until - 1));
				full = true;
			}
			response.getOutputStream().write(buffer, 0, len);
			// 输出
			response.getOutputStream().flush();
			//System.out.println(len + " transferred");
			stsl.registerNewBytes(len);
			if (full)
				break;
			while (!stsl.allowDownload()) {
				synchronized (this) {
					try {
						this.wait(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
		response.getOutputStream().close();
		if (fr != null)
			fr.close();
		}catch(Exception e){
			//do nothing
		}finally{
			dtl.unregisterThread();
		}
	}

	public void init() throws ServletException {
		// Put your code here
	}
}
